using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
using System.Net.Sockets;
using UnityEngine;
using Cysharp.Threading.Tasks;

// tcp client mgr
public class TCPMgr : Singleton<TCPMgr>
{
    private TcpClient tcpClient;
    private NetworkStream stream;
    private byte[] buffer = new byte[1024];
    private string receiveStr = "";
    private bool isConnect = false;

    public bool IsConnect
    {
        get
        {
            return isConnect;
        }

        set
        {
            isConnect = value;
            if(isConnect)
            {
                WhileLoop().Forget();
            }else
            {
                Close();
            }
        }
    }

    public async UniTask Connect(string ip, int port)
    {
        tcpClient = new TcpClient();
        await tcpClient.ConnectAsync(ip, port).AsUniTask();
        stream = tcpClient.GetStream();
        IsConnect = true;
        Debug.Log("connect success");
    }

    public async UniTask Send(byte[] data)
    {
        if (!IsConnect)
        {
            Debug.LogError("not connect");
            return;
        }
        await stream.WriteAsync(data, 0, data.Length);
        Debug.Log("send success");
    }

    public async UniTask Send(int id, byte[] data)
    {
        if (!IsConnect)
        {
            Debug.LogError("not connect");
            return;
        }
        var bytes = System.BitConverter.GetBytes(id);
        byte[] result = new byte[bytes.Length + data.Length];
        bytes.CopyTo(result,0);
        data.CopyTo(result,bytes.Length);

        // await stream.WriteAsync(result, 0, result.Length);
        await Send(result);
        Debug.Log("send success");
    }

    public async UniTask Receive()
    {
        if (!IsConnect)
        {
            Debug.LogError("not connect");
            return ;
        }
        int length = await stream.ReadAsync(buffer, 0, buffer.Length);
        var bytes = new byte[length];
        System.Buffer.BlockCopy(buffer, 0, bytes, 0, length);
        byte[] id = new byte[4];
        System.Array.Copy(bytes,id,4);
        int protocol_id = System.BitConverter.ToInt32(id,0);
        byte[] protocol_data = new byte[bytes.Length - 4];
        System.Array.Copy(bytes,4,protocol_data,0,protocol_data.Length);
        NetMgr.Instance.Dispatch(protocol_id,protocol_data,0);
    }

    public void Close()
    {
        if (!IsConnect)
        {
            Debug.LogError("not connect");
            return;
        }
        stream.Close();
        tcpClient.Close();
        IsConnect = false;
        Debug.Log("close success");
    }

    async UniTaskVoid WhileLoop()
    {
        Debug.Log("WhileLoop");
        while(IsConnect)
        {
            await UniTask.Yield(PlayerLoopTiming.Update);
            await Receive();
        }
        Debug.Log("WhileLoop???????????????????");
    }
}